package GPSChallenge;
import org.jdom2.*;

import GPSChallenge.movimiento.Posicion;

import java.util.ArrayList;
import java.util.Iterator;


public class Ciudad {
	
	private ArrayList<ArrayList<Cruce>> mapa;
	private int tamanio;
	
	
	public Ciudad(int tamanio){
		
		this.tamanio = tamanio;
		this.mapa = new ArrayList<ArrayList<Cruce>>() ;
		this.completarCruces(tamanio);
		this.completarCalles(tamanio);
		LimitesDelMapa.obtenerInstancia().establecerLimites(this.tamanio);
		
	}
	
	public Ciudad(Element ciudad){
		this.mapa = new ArrayList<ArrayList<Cruce>>() ;
		this.tamanio= Integer.parseInt(ciudad.getAttributeValue("tamanio"));
		this.completarCruces(tamanio);
		Iterator<Element> iteradorDeCalles = ciudad.getChildren("Calle").iterator();
		if (tamanio>0){
			for(int i=0;i<tamanio;i++){
				for(int j=0;j<tamanio;j++){
					if(i!= tamanio-1 || j!=tamanio-1){
						if(i==tamanio-1 && j<tamanio-1 ){
							Cruce unCruce=this.obtenerElementoEn(i,j);
							Cruce otroCruce=this.obtenerElementoEn(i,j+1);
							Calle unaCalle= new Calle(iteradorDeCalles.next());
							unCruce.setCalleDerecha(unaCalle);
							otroCruce.setCalleIzquierda(unaCalle);
						} else{
							if(i<tamanio-1 && j==tamanio-1){
								Cruce unCruce=this.obtenerElementoEn(i,j);
								Cruce otroCruce=this.obtenerElementoEn(i+1,j);
								Calle unaCalle = new Calle(iteradorDeCalles.next());
								unCruce.setCalleAbajo(unaCalle);
								otroCruce.setCalleArriba(unaCalle);
							}else {
								if (j<tamanio){
									Cruce unCruce=this.obtenerElementoEn(i,j);
									Cruce abajoDeUnCruce=this.obtenerElementoEn(i+1,j);
									Calle unaCalle = new Calle(iteradorDeCalles.next());
									unCruce.setCalleAbajo(unaCalle);
									abajoDeUnCruce.setCalleArriba(unaCalle);
									Cruce otroCruce2=this.obtenerElementoEn(i,j+1);
									Calle otraCalle= new Calle(iteradorDeCalles.next());
									unCruce.setCalleDerecha(otraCalle);
									otroCruce2.setCalleIzquierda(otraCalle);
								}
							}
						}
					}
				}
			
			}
		}
		LimitesDelMapa.obtenerInstancia().establecerLimites(this.tamanio);
		
	}
	
	public int getTamanio() {
		
		return this.tamanio;
	}

	
	private void completarCruces(int tamanio){
		
		for (int i=0;i<tamanio;i++){
			
			ArrayList<Cruce> fila = new ArrayList<Cruce>();
			
			for(int j=0;j<tamanio;j++){
				
				Cruce unCruce = new Cruce(new Posicion(i,j));
				fila.add(unCruce);
				
			}
			this.mapa.add(fila);
		}
	}
	
	public ArrayList<ArrayList<Cruce>> obtenerMapa(){
		
		return this.mapa;
	}
	
	public Cruce obtenerElementoEn(int unaFila, int unaColumna) {
		ArrayList<Cruce> fila = this.mapa.get(unaFila);
		return fila.get(unaColumna);
	}
	
	
    public Cruce obtenerCruceEnLaPosicion(Posicion unaPosicion){
		
		Iterator<ArrayList<Cruce>> iteradorFilas = this.mapa.iterator();
		 while ( iteradorFilas.hasNext() ) {
			 
			 Iterator<Cruce> iteradorCruces = iteradorFilas.next().iterator();
			 while ( iteradorCruces.hasNext() ) {
				 
				 Cruce unCruce = iteradorCruces.next();
				 if (unaPosicion.igualdadDePosicion(unCruce.obtenerPosicion()) )
					 return unCruce;
					  
			 }
		
		 }
		return null;
	}
	
    
	private void completarCalles(int tamanio){
		if (tamanio>0){
			for(int i=0;i<tamanio;i++){
				for(int j=0;j<tamanio;j++){
					if(i!= tamanio-1 || j!=tamanio-1){
						if(i==tamanio-1 && j<tamanio-1 ){
							Cruce unCruce=this.obtenerElementoEn(i,j);
							Cruce otroCruce=this.obtenerElementoEn(i,j+1);
							Calle unaCalle= new Calle();
							unCruce.setCalleDerecha(unaCalle);
							otroCruce.setCalleIzquierda(unaCalle);
						} else{
							if(i<tamanio-1 && j==tamanio-1){
								Cruce unCruce=this.obtenerElementoEn(i,j);
								Cruce otroCruce=this.obtenerElementoEn(i+1,j);
								Calle unaCalle = new Calle();
								unCruce.setCalleAbajo(unaCalle);
								otroCruce.setCalleArriba(unaCalle);
							}else {
								if (j<tamanio){
									Cruce unCruce=this.obtenerElementoEn(i,j);
									Cruce abajoDeUnCruce=this.obtenerElementoEn(i+1,j);
									Calle unaCalle = new Calle();
									unCruce.setCalleAbajo(unaCalle);
									abajoDeUnCruce.setCalleArriba(unaCalle);
									Cruce otroCruce2=this.obtenerElementoEn(i,j+1);
									Calle otraCalle= new Calle();
									unCruce.setCalleDerecha(otraCalle);
									otroCruce2.setCalleIzquierda(otraCalle);
								}
							}
						}
					}
				}
			
			}
		}
	}
	public Element Serializar2(){
		Element ciudad = new Element("ciudad");
		ciudad.setAttribute("tamanio",String.valueOf(tamanio));
		Element mapa = new Element("mapa");
		for (int i=0;i<tamanio;i++){
			Element fila = new Element("fila");
			for(int j=0;j<tamanio;j++){
			fila.addContent(obtenerElementoEn(j,i).Serializar());
			}
		mapa.addContent(fila);
		}
		
		ciudad.addContent(mapa);
		
		return ciudad;
		
	}
	
	public Document Serializar(){
		Document doc = new Document();
		Element ciudad = new Element("ciudad");
		doc.setRootElement(ciudad);
		ciudad.setAttribute("tamanio",String.valueOf(tamanio));
		for(int i=0;i<tamanio;i++){
			for(int j=0;j<tamanio;j++){
				if(i!= tamanio-1 || j!=tamanio-1){
					if(i==tamanio-1 && j<tamanio-1 ){
						Cruce unCruce=this.obtenerElementoEn(i,j);
						ciudad.addContent((unCruce.getCalleDerecha()).Serializar());
					} else{
						if(i<tamanio-1 && j==tamanio-1){
							Cruce unCruce=this.obtenerElementoEn(i,j);
							ciudad.addContent(unCruce.getCalleAbajo().Serializar());
						}else {
							if (j<tamanio){
								Cruce unCruce=this.obtenerElementoEn(i,j);
								ciudad.addContent(unCruce.getCalleAbajo().Serializar());
								ciudad.addContent(unCruce.getCalleDerecha().Serializar());
							}
						}
					}
				}
			}		
		}
		return doc;
	}
}
	
